package com.speedchina.common.upload.utils;

import com.alibaba.excel.converters.AutoConverter;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.metadata.CellData;
import com.csvreader.CsvReader;
import com.speedchina.common.download.base.CSVConfiguration;
import com.speedchina.common.download.utils.CsvWriter;
import com.speedchina.common.domain.ConversionErrorResult;
import com.speedchina.common.domain.ConversionResults;
import com.speedchina.common.exception.ConverterException;
import com.speedchina.framework.exception.BException;
import com.speedchina.framework.utils.DateUtils;
import com.speedchina.framework.utils.ReflectionUtils;
import com.speedchina.framework.validator.ValidatorHelper;
import com.speedchina.framework.validator.group.AddGroup;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 读取csv数据到list<实体中>
 * @author ZhangWC
 * @date 2021/6/28
 */
public class CsvReadUtils {

    private CsvReadUtils(){}

    /**
     * 获取到csv中的数据放到实体中返回
     * author: ZhangWC
     * date: 2021/6/29
     * [file：文件, divider：分割符, codingFormat：编码格式, clazz：模板实体字节码]
     * @return java.util.List
     */
    public static List readRawData(InputStream file, char divider, String codingFormat, Class clazz) throws IOException, IllegalAccessException, InstantiationException {

        // 第一参数：读取文件的路径 第二个参数：分隔符 第三个参数：字符集
        CsvReader csvReader = new CsvReader(file, divider, Charset.forName(codingFormat));
        // 如果你的文件没有表头，这行不用执行,这行不要是为了从表头的下一行读，也就是过滤表头
        csvReader.readHeaders();
        //获取到实体的配置信息
        List<CSVConfiguration> csvConfigurationList = CsvWriter.getCSVConfiguration(clazz);
        List resultList = new ArrayList<>();
        // 读取每行的内容
        while (csvReader.readRecord()) {
            //创建当前实体对象
            Object obj = clazz.newInstance();
            csvConfigurationList.forEach(csvConfiguration -> {
                try {
                    Object value = csvReader.get(csvConfiguration.getHead());
                    if (csvConfiguration.getField().getType() == Date.class) {
                        if (!StringUtils.isEmpty(String.valueOf(value))) {
                            value = DateUtils.getDateByDataString(String.valueOf(value),csvConfiguration.getDataFormat());
                        }
                    }
                    //通过反射给各属性赋值
                    ReflectionUtils.setFieldValue(obj,csvConfiguration.getField().getName(),value);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
            //添加到list
            resultList.add(obj);
        }
        return resultList;
    }

    public static ConversionResults readRawDataConverter(InputStream file, char divider, String codingFormat, Class clazz) throws IOException, IllegalAccessException, InstantiationException  {

        // 第一参数：读取文件的路径 第二个参数：分隔符 第三个参数：字符集
        CsvReader csvReader = new CsvReader(file, divider, Charset.forName(codingFormat));
        // 如果你的文件没有表头，这行不用执行,这行不要是为了从表头的下一行读，也就是过滤表头
        csvReader.readHeaders();
        //获取到实体的配置信息
        List<CSVConfiguration> csvConfigurationList = CsvWriter.getCSVConfiguration(clazz);
        List resultList = new ArrayList<>();
        List<ConversionErrorResult> errorResult = new ArrayList<>();
        // 读取每行的内容
        while (csvReader.readRecord()) {
            //创建当前实体对象
            Object obj = clazz.newInstance();
            for (CSVConfiguration csvConfiguration : csvConfigurationList) {
                try {
                    //获取到当前值
                    Object value = csvReader.get(csvConfiguration.getHead());
                    //获取到转换器
                    Converter converter = csvConfiguration.getConverter();
                    //不是默认转换才需要获取转换值
                    if (!AutoConverter.class.isInstance(csvConfiguration.getConverter())){
                        CellData<Object> cellData = new CellData<>(value);
                        try {
                            value = converter.convertToJavaData(cellData,null,null);
                        } catch (ConverterException e){
                            //此处获取到转换错误结果
                            ConversionErrorResult conversionErrorResult = new ConversionErrorResult(csvConfiguration.getHead(), csvReader.getCurrentRecord() + 1, e.getExceptionMsg());
                            errorResult.add(conversionErrorResult);
                        }
                        catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("========>" + csvConfiguration.getField().getType());
                    if (csvConfiguration.getField().getType() == Date.class) {
                        if (!StringUtils.isEmpty(value)) {
                            value = DateUtils.getDateByDataString(String.valueOf(value),csvConfiguration.getDataFormat());
                        }
                    }
                    //通过反射给各属性赋值
                    ReflectionUtils.setFieldValue(obj,csvConfiguration.getField().getName(), value);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            try {
                //新增校验
                ValidatorHelper.validateEntity(obj, AddGroup.class);
            }catch (BException e){
                //错误信息添加
                ConversionErrorResult conversionErrorResult = new ConversionErrorResult(null, csvReader.getCurrentRecord() + 1, e.getMessage());
                errorResult.add(conversionErrorResult);
            }
            //添加到list
            resultList.add(obj);
        }
        return new ConversionResults(resultList,errorResult);
    }

    public static List readRawDataConverter2(InputStream var1, char var2, String var3, Class clazz) throws IOException {

        // 第一参数：读取文件的路径 第二个参数：分隔符（不懂仔细查看引用百度百科的那段话） 第三个参数：字符集
        CsvReader csvReader = new CsvReader(var1, var2, Charset.forName(var3));

        // 如果你的文件没有表头，这行不用执行
        // 这行不要是为了从表头的下一行读，也就是过滤表头
        csvReader.readHeaders();
        //获取到实体的配置信息
        List<CSVConfiguration> csvConfiguration = CsvWriter.getCSVConfiguration(clazz);
        // 读取每行的内容
        while (csvReader.readRecord()) {
            // 获取内容的两种方式
            // 1. 通过下标获取 TODO 此处需要直接往实体中设置值然后返回list
            System.out.print(csvReader.get(0));
            // 2. 通过表头的文字获取
            System.out.println("----------》" + csvReader.get("昵称"));
        }
        return null;
    }
}
